package com.pan.hisystem.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.pan.hisystem.pojo.RespBean;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.List;

/**
 * @Description 上传文件控制器(有个bug没解决，就是前端无法在需要验证的情况调用接口，会被拦截，显示尚未登录，解决不了只能先放行后期在搞搞看)技术难题
 * @Author jia
 * @Date 2022/3/7 17:03
 * @Version 1.0
 **/
@RestController
@CrossOrigin
@RequestMapping("/files")
public class FileController {

    private final String ip = "http://localhost";
    @Value("${server.port}")
    private String port;

    /**
     * @param file 上传过来的文件
     * @功能描述 上传文件到服务器
     */
    @ApiOperation(value = "上传文件")
    @PostMapping("/headImage/upload")
    public RespBean upload(MultipartFile file) {
        System.out.println("前端进入上传图片接口");

        if (file == null) {
            return RespBean.error("文件不存在");
        } else {
            //获取到上传的文件名及后缀
            //如果是postman，需要设置一个工作目录，不然发送的文件为null
            //设置教程：https://blog.csdn.net/qq_36533690/article/details/104727628
            //设置完以上设置，如果还为null，检查参数名是否写错，正确的参数名为file  参数类型为File
            String originalFilename = file.getOriginalFilename();

            //通过SyStem类，获取系统参数，user.dir 表示当前项目路径
            //我们需要拼接到我们存放上传文件的路径中去
            //为了防止文件名重复，导致覆盖，我们可以设置一个uuid拼接到我们的文件名前
            String flag = IdUtil.fastSimpleUUID();

            String rootFilePath = System.getProperty("user.dir")
                    + "/hospital-demo/src/main/resources/files/headImage/" + flag + "_" + originalFilename;

            try {

                // 使用hutool的IO流工具类，将文件以流的形式输出到文件夹中
                // hutool，是一个java常用工具类库，里面分装了java开发，常用的工具类
                FileUtil.writeBytes(file.getBytes(), rootFilePath);

                return RespBean.success("文件上传成功", ip + ":" + port + "/files/headImage/download/" + flag);

            } catch (IOException e) {
                System.out.println("失败了");
                return RespBean.error("文件上传失败，请稍后重试");
            }
        }
    }

    /**
     * @param flag     指想要下载的文件名字
     * @param response HttpServletResponse
     * @功能描述 下载文件:通过使用hutool工具类，将文件通过response写给客户端
     */
    @ApiOperation(value = "下载文件")
    @GetMapping(value = "/headImage/download/{flag}",produces = "image/jpeg")
    public void download(@PathVariable("flag") String flag, HttpServletResponse response) {
        //创建一个输出流对象
        OutputStream os;

        //上传的文件根路径，也就是保存文件的地方
        String basePath = System.getProperty("user.dir")
                + "/hospital-demo/src/main/resources/files/headImage/";

        //获取该路径下的所以文件名
        List<String> fileNames = FileUtil.listFileNames(basePath);

        //找到和参数一致的文件名
        String fileName = fileNames.stream().
                filter(name -> name.contains(flag)).findAny().orElse("");


        try {
            //判断有没有这个文件
            if (StrUtil.isNotEmpty(fileName)) {
                //添加下载文件需要的响应头
                response.addHeader("Content-Disposition",
                        "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
                response.setContentType("application/octet-stream");

                //通过文件的路径读取文件字节流
                byte[] bytes = FileUtil.readBytes(basePath + fileName);

                //通过输出流返回文件
                os = response.getOutputStream();
                os.write(bytes);
                os.flush();
                os.close();
            }
        } catch (Exception e) {
            System.out.println("文件下载失败");
        }

    }

    @ApiOperation(value = "上传文件")
    @PostMapping("/testsImage/upload")
    public RespBean uploadTestsImage(MultipartFile file) {
        System.out.println("前端进入上传图片接口");

        if (file == null) {
            return RespBean.error("文件不存在");
        } else {
            //获取到上传的文件名及后缀
            //如果是postman，需要设置一个工作目录，不然发送的文件为null
            //设置教程：https://blog.csdn.net/qq_36533690/article/details/104727628
            //设置完以上设置，如果还为null，检查参数名是否写错，正确的参数名为file  参数类型为File
            String originalFilename = file.getOriginalFilename();

            //通过SyStem类，获取系统参数，user.dir 表示当前项目路径
            //我们需要拼接到我们存放上传文件的路径中去
            //为了防止文件名重复，导致覆盖，我们可以设置一个uuid拼接到我们的文件名前
            String flag = IdUtil.fastSimpleUUID();

            String rootFilePath = System.getProperty("user.dir")
                    + "/hospital-demo/src/main/resources/files/testsImage/" + flag + "_" + originalFilename;

            try {

                // 使用hutool的IO流工具类，将文件以流的形式输出到文件夹中
                // hutool，是一个java常用工具类库，里面分装了java开发，常用的工具类
                FileUtil.writeBytes(file.getBytes(), rootFilePath);

                return RespBean.success("文件上传成功", ip + ":" + port + "/files/testsImage/download/" + flag);

            } catch (IOException e) {
                System.out.println("失败了");
                return RespBean.error("文件上传失败，请稍后重试");
            }
        }
    }

    /**
     * @param flag     指想要下载的文件名字
     * @param response HttpServletResponse
     * @功能描述 下载文件:通过使用hutool工具类，将文件通过response写给客户端
     */
    @ApiOperation(value = "下载文件")
    @GetMapping(value = "/testsImage/download/{flag}",produces = "image/jpeg")
    public void downloadTestsImage(@PathVariable("flag") String flag, HttpServletResponse response) {
        //创建一个输出流对象
        OutputStream os;

        //上传的文件根路径，也就是保存文件的地方
        String basePath = System.getProperty("user.dir")
                + "/hospital-demo/src/main/resources/files/testsImage/";

        //获取该路径下的所以文件名
        List<String> fileNames = FileUtil.listFileNames(basePath);

        //找到和参数一致的文件名
        String fileName = fileNames.stream().
                filter(name -> name.contains(flag)).findAny().orElse("");


        try {
            //判断有没有这个文件
            if (StrUtil.isNotEmpty(fileName)) {
                //添加下载文件需要的响应头
                response.addHeader("Content-Disposition",
                        "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
                response.setContentType("application/octet-stream");

                //通过文件的路径读取文件字节流
                byte[] bytes = FileUtil.readBytes(basePath + fileName);

                //通过输出流返回文件
                os = response.getOutputStream();
                os.write(bytes);
                os.flush();
                os.close();
            }
        } catch (Exception e) {
            System.out.println("文件下载失败");
        }

    }
}
